import Cesium from "./Cesium"

export default () => {

  function AddImageRequest({ index, image, resolve, reject }) {
    this.index = index
    this.image = image
    this.resolve = resolve
    this.reject = reject
    this.rectangle = undefined
  }

  /**
   * 修正大量icon text atlas纹理的溢出
   * version 1.131
   */
  Cesium.TextureAtlas.prototype._resize = function (context, queueOffset = 0) {
    const borderPadding = this._borderWidthInPixels
    const oldRectangles = this._rectangles
    const queue = this._imagesToAddQueue
    const oldTexture = this._texture
    let width = oldTexture.width
    let height = oldTexture.height
    const subRegions = this._subRegions
    const toPack = oldRectangles
      .map((image, index) => {
        return new AddImageRequest({ index, image })
      })
      .filter(
        (request, index) =>
          Cesium.defined(request.image) && !Cesium.defined(subRegions.get(index)),
      )
    let maxWidth = 0
    let maxHeight = 0
    let areaQueued = 0
    for (let i = queueOffset; i < queue.length; ++i) {
      const { width: width2, height: height2 } = queue[i].image
      maxWidth = Math.max(maxWidth, width2)
      maxHeight = Math.max(maxHeight, height2)
      areaQueued += width2 * height2
      toPack.push(queue[i])
    }
    width = Math.max(maxWidth, width)
    height = Math.max(maxHeight, height)
    if (!context.webgl2) {
      width = Cesium.Math.nextPowerOfTwo(width)
      height = Cesium.Math.nextPowerOfTwo(height)
    }
    const areaDifference = areaQueued
    let scalingFactor = 2
    while (areaDifference / width / height >= 1) {
      if (width > height) {
        height *= scalingFactor
      } else {
        width *= scalingFactor
      }
    }
    toPack.sort(
      ({ image: imageA }, { image: imageB }) =>
        imageB.height * imageB.width - imageA.height * imageA.width,
    )
    const newRectangles = new Array(this._nextIndex)
    for (const index of this._subRegions.keys()) {
      if (Cesium.defined(subRegions.get(index))) {
        newRectangles[index] = oldRectangles[index]
      }
    }
    let texturePacker,
      packed = false
    while (!packed) {
      texturePacker = new Cesium.TexturePacker({ height, width, borderPadding })
      let i
      for (i = 0; i < toPack.length; ++i) {
        const { index, image } = toPack[i]
        if (!Cesium.defined(image)) {
          continue
        }
        const repackedNode = texturePacker.pack(index, image)
        if (!Cesium.defined(repackedNode)) {
          if (width > height) {
            height *= 2
          } else {
            width *= 2
          }
          break
        }
        newRectangles[index] = repackedNode.rectangle
      }
      packed = i === toPack.length
    }
    this._texturePacker = texturePacker
    this._texture = this._copyFromTexture(context, width, height, newRectangles)
    oldTexture.destroy()
    this._rectangles = newRectangles
    this._guid = Cesium.createGuid()
  }

  /**
   * 修正帧数低
   * version 1.131
   */
  const fromGltf = Cesium.Model3DTileContent.fromGltf
  Cesium.Model3DTileContent.fromGltf = async function (tileset, tile, resource, gltf) {
    const content = await fromGltf(tileset, tile, resource, gltf)
    content._model._opaquePass = Cesium.Pass.OPAQUE
    return content
  }


  const fromB3dm = Cesium.Model3DTileContent.fromB3dm
  Cesium.Model3DTileContent.fromB3dm = async function (tileset, tile, resource, gltf) {
    const content = await fromB3dm(tileset, tile, resource, gltf)
    content._model._opaquePass = Cesium.Pass.OPAQUE
    return content
  }
}
